package com.xyht.sca_s.student_manage_system.modules.appDynamic.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonCodeEnum;
import com.xyht.sca_s.student_manage_system.common.commonReturn.CommonResult;
import com.xyht.sca_s.student_manage_system.common.commonReturn.ResponseResult;
import com.xyht.sca_s.student_manage_system.common.util.CacheUtil;
import com.xyht.sca_s.student_manage_system.common.util.PinYinUtil;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.*;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.req.AppBasicInfoReq;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.resp.AppApplicationUserResp;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.resp.AppBasicInfoResp;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.entity.resp.UserInfoResp;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.mapper.*;
import com.xyht.sca_s.student_manage_system.modules.appDynamic.service.AppBasicInfoService;
import com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTips;
import com.xyht.sca_s.student_manage_system.modules.newTips.entity.SmsNewTipsRecord;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsMapper;
import com.xyht.sca_s.student_manage_system.modules.newTips.mapper.SmsNewTipsRecordMapper;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsApplication;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsApplicationType;
import com.xyht.sca_s.student_manage_system.modules.user.entity.SmsUser;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsApplicationMapper;
import com.xyht.sca_s.student_manage_system.modules.user.mapper.SmsApplicationTypeMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MaxUploadSizeExceededException;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

import static com.xyht.sca_s.student_manage_system.common.util.ParamCheckUtil.isNullOrEmpty;
import static com.xyht.sca_s.student_manage_system.modules.appDynamic.constant.BooleanConstant.DYNAMIC_APP_TRUE;
import static com.xyht.sca_s.student_manage_system.modules.appDynamic.constant.NodeTypeConstant.CONDITION_NODE;
import static com.xyht.sca_s.student_manage_system.modules.common.constant.FileSavePathConstant.*;

/**
 * <p>
 * 应用基础信息表 服务实现类
 * </p>
 *
 * @author XYHT
 * @since 2023-07-26
 */
@Service
public class AppBasicInfoServiceImpl extends ServiceImpl<AppBasicInfoMapper, AppBasicInfo> implements AppBasicInfoService {
    @Resource
    private AppBasicInfoMapper appBasicInfoMapper;
    @Resource
    private CacheUtil cacheUtil;
    @Resource
    private SmsApplicationMapper smsApplicationMapper;
    @Resource
    private PinYinUtil pinYinUtil;
    @Resource
    private SmsApplicationTypeMapper smsApplicationTypeMapper;
    @Resource
    private AppApplicationMapper appApplicationMapper;
    @Resource
    private AppApplicationDataMapper appApplicationDataMapper;
    @Resource
    private AppControlOrderMapper appControlOrderMapper;
    @Resource
    private AppTextControlConfigMapper appTextControlConfigMapper;
    @Resource
    private AppTimeControlConfigMapper appTimeControlConfigMapper;
    @Resource
    private AppOptionControlConfigMapper appOptionControlConfigMapper;
    @Resource
    private AppFileControlConfigMapper appFileControlConfigMapper;
    @Resource
    private AppStepperControlConfigMapper appStepperControlConfigMapper;
    @Resource
    private AppProcessNodeConfigMapper appProcessNodeConfigMapper;
    @Resource
    private AppProcessNodeDetailMapper appProcessNodeDetailMapper;
    @Resource
    private AppProcessRollbackRecordMapper appProcessRollbackRecordMapper;
    @Resource
    private AppConditionMapper appConditionMapper;
    @Resource
    private AppConditionGroupMapper appConditionGroupMapper;
    @Resource
    private SmsNewTipsMapper smsNewTipsMapper;
    @Resource
    private SmsNewTipsRecordMapper smsNewTipsRecordMapper;
    @Resource
    private AppTemplateMapper appTemplateMapper;
    @Resource
    private FileSavePathConstant fileSavePathConstant;

    @Override
    @Transactional
    public ResponseResult addAppBasicInfo(AppBasicInfoReq basicInfoReq, String userId) {
        //校验参数
        if (isNullOrEmpty(basicInfoReq.getAppIcon(), basicInfoReq.getAppName(), basicInfoReq.getAppExplain(),
                basicInfoReq.getAppFenLei(), basicInfoReq.getAppPath(), basicInfoReq.getAppSwitch(), basicInfoReq.getAppType(),
                basicInfoReq.getAppClientList(), basicInfoReq.getMakerId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验应用管理员是否传入
        if (JSON.parseArray(basicInfoReq.getMakerId(), String.class).size() == 0) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_ADD_ERROR_MANAGER_NOT_EXIST);
        }
        //校验应用名称是否重复
        Integer count = smsApplicationMapper.selectCount(new LambdaQueryWrapper<SmsApplication>()
                .eq(SmsApplication::getAppName, basicInfoReq.getAppName()));
        Integer newAppCount = appBasicInfoMapper.selectCount(new LambdaQueryWrapper<AppBasicInfo>()
                .eq(AppBasicInfo::getAppName, basicInfoReq.getAppName()));
        if (count > 0 || newAppCount > 0) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_ADD_ERROR_NAME_DUPLICATION);
        }

        AppBasicInfo appBasicInfo = new AppBasicInfo();
        BeanUtils.copyProperties(basicInfoReq, appBasicInfo, "id");
        appBasicInfo.setAppClientList(basicInfoReq.getAppClientList().toString());

        //校验 appType 是否重复
        List<AppBasicInfo> appBasicInfoList = appBasicInfoMapper.selectList(new LambdaQueryWrapper<AppBasicInfo>()
                .eq(AppBasicInfo::getAppType, basicInfoReq.getAppType()));
        if (!appBasicInfoList.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_ADD_ERROR);
        }
        appBasicInfoMapper.insert(appBasicInfo);

        for (Integer appClient : basicInfoReq.getAppClientList()) {
            SmsApplication smsApplication = new SmsApplication();
            BeanUtils.copyProperties(basicInfoReq, smsApplication, "id");
            smsApplication.setIsAppNew(DYNAMIC_APP_TRUE);
            smsApplication.setAppDescription(basicInfoReq.getAppExplain());
            smsApplication.setUpDown(basicInfoReq.getAppSwitch());
            smsApplication.setAppPosition(1);
            smsApplication.setNewAppId(appBasicInfo.getId());
            String spellStr = pinYinUtil.getHanZiPY(basicInfoReq.getAppName());
            smsApplication.setAppSpell(spellStr);
            smsApplication.setAppTypeId(basicInfoReq.getAppFenLei());
            smsApplication.setAppClient(appClient);
            smsApplicationMapper.insert(smsApplication);
        }
        return CommonResult.success(appBasicInfo.getId());
    }

    @Override
    @Transactional
    public ResponseResult deletedAppBasicInfo(AppBasicInfoReq basicInfoReq) {
        //校验参数
        if (isNullOrEmpty(basicInfoReq.getId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        String appId = basicInfoReq.getId();
        //校验应用是否存在
        AppBasicInfo appBasicInfo = appBasicInfoMapper.selectById(appId);
        if (isNullOrEmpty(appBasicInfo)) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_NOT_EXIST);
        }
        //删除动态应用
        appBasicInfoMapper.deleteById(appId);
        //删除界面应用
        smsApplicationMapper.delete(new LambdaQueryWrapper<SmsApplication>().eq(SmsApplication::getNewAppId, appId));
        //删除应用模板
        appTemplateMapper.delete(new LambdaQueryWrapper<AppTemplate>().eq(AppTemplate::getAppId, appId));
        //查询申请表数据
        List<AppApplication> appApplicationList = appApplicationMapper.selectList(new LambdaQueryWrapper<AppApplication>()
                .eq(AppApplication::getAppId, appId));
        if (!appApplicationList.isEmpty()) {
            //删除申请表数据
            List<String> applicationIdList = appApplicationList.stream().map(AppApplication::getId).collect(Collectors.toList());
            appApplicationDataMapper.delete(new LambdaQueryWrapper<AppApplicationData>().in(AppApplicationData::getApplicationId, applicationIdList));
            //删除消息
            List<SmsNewTips> smsNewTipList = smsNewTipsMapper.selectList(new LambdaQueryWrapper<SmsNewTips>().in(SmsNewTips::getEventId, applicationIdList));
            if (!smsNewTipList.isEmpty()) {
                List<String> newTipsIdList = smsNewTipList.stream().map(SmsNewTips::getId).collect(Collectors.toList());
                smsNewTipsMapper.deleteBatchIds(newTipsIdList);
                smsNewTipsRecordMapper.delete(new LambdaQueryWrapper<SmsNewTipsRecord>().in(SmsNewTipsRecord::getRecordTipsId, newTipsIdList));
            }
            //删除申请表
            appApplicationMapper.deleteBatchIds(applicationIdList);
        }
        //删除控件
        appControlOrderMapper.delete(new LambdaQueryWrapper<AppControlOrder>().eq(AppControlOrder::getAppId, appId));
        appTextControlConfigMapper.delete(new LambdaQueryWrapper<AppTextControlConfig>().eq(AppTextControlConfig::getAppId, appId));
        appTimeControlConfigMapper.delete(new LambdaQueryWrapper<AppTimeControlConfig>().eq(AppTimeControlConfig::getAppId, appId));
        appOptionControlConfigMapper.delete(new LambdaQueryWrapper<AppOptionControlConfig>().eq(AppOptionControlConfig::getAppId, appId));
        appFileControlConfigMapper.delete(new LambdaQueryWrapper<AppFileControlConfig>().eq(AppFileControlConfig::getAppId, appId));
        appStepperControlConfigMapper.delete(new LambdaQueryWrapper<AppStepperControlConfig>().eq(AppStepperControlConfig::getAppId, appId));
        //删除节点(NodeDetail)
        appProcessNodeDetailMapper.delete(new LambdaQueryWrapper<AppProcessNodeDetail>().eq(AppProcessNodeDetail::getAppId, appId));
        appProcessRollbackRecordMapper.delete(new LambdaQueryWrapper<AppProcessRollbackRecord>().eq(AppProcessRollbackRecord::getAppId, appId));
        //删除条件
        List<AppProcessNodeConfig> nodeConfigList = appProcessNodeConfigMapper.selectList(new LambdaQueryWrapper<AppProcessNodeConfig>()
                .eq(AppProcessNodeConfig::getAppId, appId)
                .eq(AppProcessNodeConfig::getType, CONDITION_NODE));
        if (!nodeConfigList.isEmpty()) {
            List<String> conditionNodeIdList = nodeConfigList.stream().map(AppProcessNodeConfig::getId).collect(Collectors.toList());
            appConditionGroupMapper.delete(new LambdaQueryWrapper<AppConditionGroup>().in(AppConditionGroup::getNodeId, conditionNodeIdList));
            appConditionMapper.delete(new LambdaQueryWrapper<AppCondition>().in(AppCondition::getNodeId, conditionNodeIdList));
        }
        //最后删除节点配置
        appProcessNodeConfigMapper.delete(new LambdaQueryWrapper<AppProcessNodeConfig>().eq(AppProcessNodeConfig::getAppId, appId));
        return CommonResult.success();
    }

    @Override
    @Transactional
    public ResponseResult updateAppBasicInfo(AppBasicInfoReq basicInfoReq, String userId) {
        //校验参数
        if (isNullOrEmpty(basicInfoReq.getId(), basicInfoReq.getAppIcon(), basicInfoReq.getAppName(), basicInfoReq.getAppExplain(),
                basicInfoReq.getAppFenLei(), basicInfoReq.getAppPath(), basicInfoReq.getAppSwitch(), basicInfoReq.getAppType(),
                basicInfoReq.getAppClientList(), basicInfoReq.getMakerId())) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验应用管理员是否传入
        if (JSON.parseArray(basicInfoReq.getMakerId(), String.class).size() == 0) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_ADD_ERROR_MANAGER_NOT_EXIST);
        }
        AppBasicInfo appBasicInfo = appBasicInfoMapper.selectById(basicInfoReq.getId());
        if (isNullOrEmpty(appBasicInfo)) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_NOT_EXIST);
        }
        //appType不可修改
        if (!appBasicInfo.getAppType().equals(basicInfoReq.getAppType())) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_ADD_ERROR_APP_TYPE_DUPLICATION);
        }
        //校验应用名称是否重复
        Integer count = smsApplicationMapper.selectCount(new LambdaQueryWrapper<SmsApplication>()
                .eq(SmsApplication::getAppName, basicInfoReq.getAppName())
                .ne(SmsApplication::getAppName, appBasicInfo.getAppName()));
        Integer newAppCount = appBasicInfoMapper.selectCount(new LambdaQueryWrapper<AppBasicInfo>()
                .eq(AppBasicInfo::getAppName, basicInfoReq.getAppName())
                .ne(AppBasicInfo::getAppName, appBasicInfo.getAppName()));
        if (count > 0 || newAppCount > 0) {
            return CommonResult.failed(CommonCodeEnum.DYNAMIC_APP_ADD_ERROR_NAME_DUPLICATION);
        }

        AppBasicInfo basicInfo = new AppBasicInfo();
        BeanUtils.copyProperties(basicInfoReq, basicInfo);
        basicInfo.setAppClientList(JSONObject.toJSONString(basicInfoReq.getAppClientList()));
        appBasicInfoMapper.updateById(basicInfo);

        //修改smsApplication表
        QueryWrapper<SmsApplication> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(SmsApplication::getNewAppId, basicInfoReq.getId());
        List<SmsApplication> list = smsApplicationMapper.selectList(queryWrapper);
        if (isNullOrEmpty(list) || list.size() < 1) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }

        List<Integer> list1 = list.stream().map(SmsApplication::getAppClient).collect(Collectors.toList());

        //如果SmsApplication中client的集合比前端传过来的client的集合大
        //获取前端传过来的集合和SmsApplication中的client的集合的交集
        //对交集进行修改并且删除补集
        Set<Integer> intersection = new HashSet<>(list1);
        intersection.retainAll(basicInfoReq.getAppClientList());

        for (Integer appClient : intersection) {
            QueryWrapper<SmsApplication> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.lambda().eq(SmsApplication::getNewAppId, basicInfoReq.getId())
                    .eq(SmsApplication::getAppClient, appClient);
            SmsApplication application = smsApplicationMapper.selectOne(queryWrapper1);
            if (isNullOrEmpty(application)) {
                return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
            }
            BeanUtils.copyProperties(basicInfoReq, application);
            String spellStr = pinYinUtil.getHanZiPY(basicInfoReq.getAppName());
            application.setAppSpell(spellStr);
            application.setAppDescription(basicInfoReq.getAppExplain());
            smsApplicationMapper.updateById(application);
        }

        if (list1.size() > basicInfoReq.getAppClientList().size()) {
            //求出list1的补集complementA
            HashSet<Integer> complementA = new HashSet<>(list1);
            complementA.removeAll(basicInfoReq.getAppClientList());
            for (Integer complement : complementA) {
                smsApplicationMapper.delete(new LambdaQueryWrapper<SmsApplication>()
                        .eq(SmsApplication::getNewAppId, basicInfoReq.getId())
                        .eq(SmsApplication::getAppClient, complement));
            }
        } else if (list1.size() < basicInfoReq.getAppClientList().size()) {
            //求出basicInfoReq.getAppClientList().size()集合的补集
            HashSet<Integer> complementB = new HashSet<>(basicInfoReq.getAppClientList());
            complementB.removeAll(list1);
            for (Integer complement : complementB) {
                SmsApplication smsApplication = new SmsApplication();
                BeanUtils.copyProperties(basicInfoReq, smsApplication, "id");
                smsApplication.setIsAppNew(DYNAMIC_APP_TRUE);
                smsApplication.setAppDescription(basicInfoReq.getAppExplain());
                smsApplication.setUpDown(basicInfoReq.getAppSwitch());
                smsApplication.setAppPosition(1);
                smsApplication.setNewAppId(basicInfo.getId());
                String spellStr = pinYinUtil.getHanZiPY(basicInfoReq.getAppName());
                smsApplication.setAppSpell(spellStr);
                smsApplication.setAppTypeId(basicInfoReq.getAppFenLei());
                smsApplication.setAppClient(complement);
                smsApplicationMapper.insert(smsApplication);
            }
        }

        return CommonResult.success();
    }

    @Override
    public ResponseResult selectById(String id, String userId) {
        AppBasicInfo appBasicInfo = appBasicInfoMapper.selectById(id);
        if (isNullOrEmpty(appBasicInfo)) {
            return CommonResult.failed(CommonCodeEnum.DATA_NOT_FOUND);
        }
        AppBasicInfoResp appBasicInfoResp = new AppBasicInfoResp();
        BeanUtils.copyProperties(appBasicInfo, appBasicInfoResp);
        SmsUser smsUser = cacheUtil.getUserInfo(userId);
        UserInfoResp userInfoResp = new UserInfoResp();
        if (smsUser != null) {
            BeanUtils.copyProperties(smsUser, userInfoResp);
        }
        appBasicInfoResp.setApplyUserInfo(userInfoResp);
        List<Integer> integers = JSONObject.parseArray(appBasicInfo.getAppClientList(), Integer.class);
        appBasicInfoResp.setAppClientList(integers);
        SmsApplicationType type = smsApplicationTypeMapper.selectOne(new LambdaQueryWrapper<SmsApplicationType>()
                .eq(SmsApplicationType::getId, appBasicInfoResp.getAppFenLei()));
        if (!isNullOrEmpty(type)) {
            appBasicInfoResp.setAppCateGory(type.getTypeName());
        }

        //设置应用管理员集合
        List<String> makerIdList = JSON.parseArray(appBasicInfo.getMakerId(), String.class);
        List<AppApplicationUserResp> userRespList = makerIdList.stream().map(makerId -> {
            SmsUser userInfo = cacheUtil.getUserInfo(makerId);
            AppApplicationUserResp makerInfoResp = new AppApplicationUserResp();
            BeanUtils.copyProperties(userInfo, makerInfoResp);
            return makerInfoResp;
        }).collect(Collectors.toList());
        appBasicInfoResp.setMakerUserInfoList(userRespList);

        return CommonResult.success(appBasicInfoResp);
    }

    @Override
    public ResponseResult tableUpload(MultipartFile file, String appId) {
        //校验app是否存在
        if (isNullOrEmpty(appId) || isNullOrEmpty(appBasicInfoMapper.selectById(appId))) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验文件是否为空
        if (file.isEmpty()) {
            return CommonResult.failed(CommonCodeEnum.INVALID_PARAM);
        }
        //校验文件大小
        int size = Math.round((float) file.getSize() / 1024);
        if (size == fileSavePathConstant.getFILE_UPLOAD_MIN()) {
            return CommonResult.failed(CommonCodeEnum.FILE_SIZE_LIMIT_MIN);
        }

        //获取文件名
        String fileName = file.getOriginalFilename();
        log.debug(fileName + "-->" + size + "KB");
        String[] fileTypeArr = fileName.split("\\.");
        String fileType = fileTypeArr[fileTypeArr.length - 1];

        String timeStamp = String.valueOf(new Date().getTime());
        String OSName = System.getProperty("os.name");
        String filePath = OSName.toLowerCase().startsWith("win") ? fileSavePathConstant.getDYNAMIC_FILE_DOWNLOAD_PATH()
                : fileSavePathConstant.getDYNAMIC_FILE_DOWNLOAD_PATH_LINUX();
        String completePath = filePath + timeStamp + "." + fileType;
        String newFileName = timeStamp + "." + fileType;

        //保存应用模板名
        LambdaQueryWrapper<AppTemplate> queryWrapper = new LambdaQueryWrapper<AppTemplate>().eq(AppTemplate::getAppId, appId);
        Integer count = appTemplateMapper.selectCount(queryWrapper);
        if (count > 0) {
            appTemplateMapper.delete(queryWrapper);
        }
        AppTemplate template = new AppTemplate();
        template.setAppId(appId);
        template.setTemplateName(newFileName);
        appTemplateMapper.insert(template);

        File dest = new File(completePath);
        if (!dest.getParentFile().exists()) {//判断文件父目录是否存在
            //不存在重新创建
            dest.getParentFile().mkdir();
        }
        try {
            file.transferTo(dest); //保存文件
            Map<String, Object> map = new HashMap<>();
            map.put("oldFileName", fileName);
            map.put("newFileName", newFileName);
            return CommonResult.success(map);
        } catch (MaxUploadSizeExceededException e) {
            e.printStackTrace();
            return CommonResult.failed(CommonCodeEnum.FILE_SIZE_LIMIT_EXCEEDED);
        } catch (Exception e) {
            e.printStackTrace();
            return CommonResult.failed(CommonCodeEnum.FAIL);
        }
    }

}
